import Menu from "../../sql/module/menu";
import Role from "../../sql/module/user/role";
import RoleMenu from "../../sql/module/_dictionaries/role_menu";
import auth from "../../middlewares/auth";
import { Forbbidend, NotFound, NotFoundItem, Success } from "../../code/http-exception";
import { AddRoleValidator } from "../../validators/role_menu";
import log from "../../middlewares/log";
import { InfoValidator } from "../../validators/public";
import { LOGTYPE } from "../../lib/enum";

Role.belongsToMany(Menu, { through: RoleMenu });
Menu.belongsToMany(Role, { through: RoleMenu });
const router: Api = new Map()

//菜单列表用于身份添加、修改
router.set('/menus', [auth(['addRole', 'updateRole']), async () => {
    const menus: any[] = []
    const fun: (sub: any[], upLevel: string | null) => any = async (sub, upLevel) => {
        const menus = await Menu.findAll({
            attributes: ['id', 'label', 'url', 'type', 'public'],
            where: { upLevel, state: 1 },
            include: {
                attributes: [],
                model: Role
            }
        })
        await Promise.all(menus.map(async item => {
            const it = { ...item.dataValues }
            sub.push(it)
            it.sub = []
            return fun(it.sub, item.dataValues.url)
        }))
    }
    await fun(menus, null)
    throw new Success(menus)
}])

//身份列表
router.set('/roleList', [auth('rolelist'), async (ctx, next) => {
    const rows = await Role.findAll({
        attributes: { exclude: ['updatedAt'] },
        include: {
            model: Menu, required: false, attributes: ['id', 'label', 'url'], where: { state: 1 }
        }
    })
    const count = await Role.count()
    throw new Success({ list: rows, total: count })
}])


//身份详情
router.set('/getInfo', [auth('updateRole'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const role = await Role.findOne({
        where: { id: v.get('query.id') },
        include: { model: Menu, required: false, attributes: ['id', 'label', 'url'], where: { state: 1 } }
    })
    throw new Success(role)
}])

//修改身份
router.set('/updateRole', [auth('updateRole'), async (ctx, next) => {
    const v = await new AddRoleValidator().validate(ctx)
    const id = v.get('query.id')
    const name = v.get('body.name')
    const uid = v.get('body.uid')
    const menus = v.get('body.menus')
    ctx.from = await Role.findOne({
        where: { id },
        include: { model: Menu, attributes: [['label', 'name'], 'id'] }
    })
    if (!ctx.from) throw new NotFound()
    await Role.update({
        name, uid
    }, { where: { id } })
    await RoleMenu.destroy({
        where: {
            RoleId: id
        }
    })
    await RoleMenu.bulkCreate(menus.map((item: any) => ({
        MenuId: item,
        RoleId: id
    })))
    ctx.to = await Role.findOne({
        where: { id },
        include: { model: Menu, attributes: [['label', 'name'], 'id'] }
    })
    await next()
    throw new Success('请求成功', 20000)
}, log((ctx) => '修改了' + ctx.from.name + '的详情', "/api/v1/role/recoverInfo", "update")])

//恢复身份信息
router.set('/recoverInfo', [auth('resetRecord'), async ctx => {
    console.log(95)
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const dff = JSON.parse(v.get('body.dff'))
    if (dff.Menus.length > 0) {
        await RoleMenu.destroy({ where: { RoleId: id } })
        await RoleMenu.bulkCreate(dff.Menus
            .filter((item: any) => item.type !== LOGTYPE.add).map((item: any) => ({
                RoleId: id,
                MenuId: item.id
            })))
    }
    delete dff.Menus
    const role = await Role.findOne({
        where: {
            id
        }
    })
    if (!role) throw new NotFoundItem()
    await role.update(dff)
    throw new Success()
}])

//添加身份
router.set('/addRole', [auth('addRole'), async (ctx, next) => {
    const v = await new AddRoleValidator().validate(ctx)
    const menus = v.get('body.menus')
    const uid = v.get('body.uid')
    const name = v.get('body.name')
    ctx.to = {
        name,
        uid
    }
    const role = await Role.create(ctx.to)
    ctx._id = role.dataValues.id
    ctx.name = role.dataValues.name
    await RoleMenu.bulkCreate(menus.map((item: any) => ({
        MenuId: item,
        RoleId: role.dataValues.id
    })))
    await next()
    throw new Success('请求成功', 20000)
}, log((ctx) => '添加了一个身份:' + ctx.name, '/api/v1/role/delete', 'create')])

//删除身份
router.set('/delete', [auth('deleteRole'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const uids = [0, 1, 2, 100]
    const role = await Role.findOne({
        where: { id }
    })
    if (!role) { throw new NotFoundItem() }
    const uid = role?.dataValues.uid
    if (uids.includes(uid)) {
        throw new Forbbidend('预设权限禁止删除')
    }
    if (ctx.auth.uid.includes(uid)) {
        throw new Forbbidend('禁止删除自己的身份')
    }
    await role.update({
        uid: role.dataValues.uid * 1 - 101
    })
    await role.destroy()
    ctx._id = id
    ctx.name = role.dataValues.name
    await next()
    throw new Success('删除成功', 20000)
}, log((ctx) => '删除了身份:' + ctx.name, '/api/v1/role/recover', 'delete')])

//恢复删除
router.set('/recover', [auth('resetRecord'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    await Role.restore({
        where: {
            id
        }
    })
    const role = await Role.findOne({ where: { id } })
    if (!role) { throw new NotFoundItem() }
    try {
        await role.update({
            uid: role.dataValues.uid + 101
        })
    } catch (err) {
        throw new Success('权限ID被占用，请修改后重试', 20001)
    }
    throw new Success('恢复成功', 20000)
}])
export { router }